package com.booter.consumer.config;

import com.booter.common.HttpConnectionManager;
import org.apache.http.client.HttpClient;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.client.DefaultResponseErrorHandler;
import org.springframework.web.client.RestTemplate;

import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

/**
 * Ribbon 依赖restTemplate
 * <p>
 * Server stats: [[Server:10.205.11.72:8080;	Zone:UNKNOWN;	Total Requests:0;	Successive connection failure:0;	Total blackout seconds:0;	Last connection made:Thu Jan 01 08:00:00 CST 1970;	First connection made: Thu Jan 01 08:00:00 CST 1970;	Active Connections:0;	total failure count in last (1000) msecs:0;	average resp time:0.0;	90 percentile resp time:0.0;	95 percentile resp time:0.0;	min resp time:0.0;	max resp time:0.0;	stddev resp time:0.0]
 * ]}ServerList:com.alibaba.cloud.nacos.ribbon.NacosServerList@1262e95c
 * 因为Ribbon的饥饿加载(eager-load)模式，造成第一次服务调用出现失败的原因主要是Ribbon进行客户端负载均衡的Client并不是在服务启动的时候就初始化好的，而是在调用的时候才会去创建相应的Client，所以第一次调用的耗时不仅仅包含发送HTTP请求的时间，还包含了创建RibbonClient的时间，这样一来如果创建时间速度较慢，
 * 同时设置的超时时间又比较短的话，就会有上述提示
 * 解决的方法就是提前创建而不是在第一次调用时创建
 * ribbon.eager-load.enabled=true  开启饥饿加载模式
 * ribbon.eager-load.clients=booter-producer 指定需要饥饿加载的客户端名称、服务名
 * 重启消费者服务后会发现服务启动后就会出现上述提示而不是在第一次调用时
 *
 * @author admin
 */
@Configuration
public class RibbonConfig {

    /***
     * 设置restTemplate 自定义异常
     */
    public class CustomErrorHandler extends DefaultResponseErrorHandler {
        @Override
        public void handleError(ClientHttpResponse response) {
            //do thing
        }
    }

    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(@Qualifier("httpRequestFactory") ClientHttpRequestFactory httpRequestFactory) {
        List<HttpMessageConverter<?>> messageConverters = new ArrayList<>();
        //text/plain
        StringHttpMessageConverter stringConverter = new StringHttpMessageConverter(StandardCharsets.UTF_8);
        MappingJackson2HttpMessageConverter jsonConverter = new MappingJackson2HttpMessageConverter();
        //FormHttpMessageConverter 读取和写入 application/x-www-form-urlencoded 介质类型,ByteArrayHttpMessageConverter
        //MappingJackson2XmlHttpMessageConverter可以注入自定义XmlMapper通过ObjectMapper属性。此转换器支持application/xml,SourceHttpMessageConverter
        //BufferedImageHttpMessageConverter,MarshallingHttpMessageConverter
        messageConverters.add(stringConverter);
        messageConverters.add(jsonConverter);

        RestTemplate restTemplate = new RestTemplate(httpRequestFactory);
        restTemplate.setMessageConverters(messageConverters);

        restTemplate.setErrorHandler(new CustomErrorHandler());
        return restTemplate;
    }

    // 1-Content-Type
//    RequestEntity<User> requestEntity = RequestEntity
//            .post(new URI(uri))
//            .contentType(MediaType.APPLICATION_JSON)
//            .body(user);

    // 2-Accept
//    RequestEntity<User> requestEntity = RequestEntity
//            .post(new URI(uri))
//            .accept(MediaType.APPLICATION_JSON)
//            .body(user);

    // 3-Other
//    RequestEntity<User> requestEntity = RequestEntity
//            .post(new URI(uri))
//            .header("Authorization", "Basic " + base64Credentials)
//            .body(user);

//FormHttpMessageConverter默认是支持这三种partConverter，所以当使用multipart/form-data时，
// multiValueMap中的值必须为String、byte[]、Resource或者HttpEntity类型，
// 但是HttpEntity中的T也必须为String、byte[]、Resource这三种之一
//    4 上传文件
//    MultiValueMap<String, Object> multiPartBody = new LinkedMultiValueMap<>();
//    multiPartBody.add("file", new ClassPathResource("/tmp/user.txt"));
//    RequestEntity<MultiValueMap<String, Object>> requestEntity = RequestEntity
//            .post(uri)
//            .contentType(MediaType.MULTIPART_FORM_DATA)
//            .body(multiPartBody);


//  MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
//	headers.add(HttpHeaders.CONTENT_TYPE, MediaType.MULTIPART_FORM_DATA_VALUE);
//  MultiValueMap<String, Object> params = new LinkedMultiValueMap<>();
//	params.add("file", new FileSystemResource(new File("C:\\xxx.png")));
//    String result = restTemplate.exchange(url, HttpMethod.POST,
//            new HttpEntity<MultiValueMap<String, Object>>(params, headers), String.class).getBody();

//   5 下载小文件
//    RequestEntity requestEntity = RequestEntity.get(uri).build();
//    ResponseEntity<byte[]> responseEntity = restTemplate.exchange(requestEntity, byte[].class);
//    byte[] downloadContent = responseEntity.getBody();


//    HttpHeaders headers = new HttpHeaders();
//    headers.setAccept(Arrays.asList(MediaType.ALL));
//    HttpEntity<byte[]> requestEntity = new HttpEntity<byte[]>(headers);
//    return restTemplate.exchange(url, HttpMethod.GET, requestEntity, byte[].class).getBody();


//  6 下载大文件
//    ResponseExtractor<ResponseEntity<File>> responseExtractor = new ResponseExtractor<ResponseEntity<File>>() {
//        @Override
//        public ResponseEntity<File> extractData(ClientHttpResponse response) throws IOException {
//            File rcvFile = File.createTempFile("rcvFile", "zip");
//            FileCopyUtils.copy(response.getBody(), new FileOutputStream(rcvFile));
//            return ResponseEntity.status(response.getStatusCode()).headers(response.getHeaders()).body(rcvFile);
//        }
//    };
//    File getFile = this.restTemplate.execute(targetUri, HttpMethod.GET, null, responseExtractor);

    @Bean
    public ClientHttpRequestFactory httpRequestFactory(@Qualifier("httpClient") HttpClient httpClient) {
        return new HttpComponentsClientHttpRequestFactory(httpClient);
    }


    @Bean
    public HttpClient httpClient() {
        HttpConnectionManager hm = new HttpConnectionManager();
        hm.init();
        return hm.getHttpClient();
    }

}
